package 反射;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
//一、Method 类的定义
//Method 类位于 java.lang.reflect 包中，主要用于在程序运行状态中，动态地获取方法信息
//二、Method 类常用方法
//
//《getAnnotatedReturnType()》
//
//返回一个 AnnotatedType 对象，该对象表示使用类型来指定由该可执行文件表示的方法或构造函数的返回类型

//import 注解.FruitName;

/*public class Method类 {
    
    public String test() {
        return null;
    }

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        AnnotatedType annotatedReturnType = method.getAnnotatedReturnType();
        // class java.lang.String
        System.out.println(annotatedReturnType.getType());
    }
}*/

//《getAnnotatedExceptionTypes()》
//
//返回一个 AnnotatedType 对象数组，这些对象表示使用类型来指定由该可执行文件表示的方法或构造函数声明的异常
//
/*public class Method类 {
    
    public void test() throws NullPointerException, ClassNotFoundException {}

    public static void main(String[] args) throws Exception {
//        Method method = Method类.class.getDeclaredMethod("test");
    	Class<Method类> cls=Method类.class;
    	Method[] me=cls.getDeclaredMethods();
    	for (Method m:me) {
    		System.out.println(m.getName()+":");
//    		System.out.println(m.toString());
    		AnnotatedType[] annotatedExceptionTypes = m.getAnnotatedExceptionTypes();
    		for (AnnotatedType annotatedExceptionType : annotatedExceptionTypes) {
            // class java.lang.NullPointerException
            // class java.lang.ClassNotFoundException
            System.out.println(annotatedExceptionType.getType());
    		}
        }
    }
}*/
//
//《getAnnotatedReceiverType()》
//
//返回一个 AnnotatedType 对象，该对象表示使用类型来指定该可执行对象表示的方法或构造函数的接收者类型
//
/*class Student1{
	String name;
	public Student1(String name) {
		this.name=name;
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String test1(String a) {return a+"aaaa";}
}
public class Method类 {
    
//    public void test() {}
    public String test() {return "aaaa";}

    public static void main(String[] args) throws Exception {
//    	Student1 str=new Student1("aaa");
//    	Method method = Method类.class.getDeclaredMethod("test");
        Method method = Student1.class.getDeclaredMethod("test1",String.class);
        AnnotatedType annotatedReceiverType = method.getAnnotatedReceiverType();
        // class 反射.Method类  class 反射.Student1
        System.out.println(annotatedReceiverType.getType());
    }
}*/
//
//《getAnnotation(Class<T> annotationClass)》
//
//如果该方法对象存在指定类型的注解，则返回该注解，否则返回 null
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotation() 方法与 getDeclaredAnnotation() 方法作用相同
//
/*@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MethodAnnotation {
    String key();
    String value();
}

public class Method类 {
    
    @MethodAnnotation(key = "key", value = "value")
//    public void test() {}
    public String test(String a) {return a+"asdasd";}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test",String.class);
        MethodAnnotation annotation = method.getAnnotation(MethodAnnotation.class);
        // @反射.MethodAnnotation(value=value, key=key)
        System.out.println(annotation);
    }
}*/
//
//《getDeclaredAnnotation(Class<T> annotationClass)》
//
//如果该方法对象存在指定类型的注解，则返回该注解，否则返回 null
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotation() 方法与 getDeclaredAnnotation() 方法作用相同
//
//《getAnnotationsByType(Class<T> annotationClass)》
//
//如果该方法对象存在指定类型的注解，则返回该注解数组，否则返回 null
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotationsByType() 方法与 getDeclaredAnnotationsByType() 方法作用相同
//
//getAnnotationsByType() 方法与 getAnnotation() 方法的区别在于：getAnnotationsByType() 方法会检查修饰该方法对象的注解是否为可
//重复类型注解，如果是则会返回修饰该方法对象的一个或多个注解
//
//@Repeatable 用于声明注解为可重复类型注解
//
//当声明为可重复类型注解后，如果方法注解仍为一个，则 getAnnotation() 方法会正常返回，如果方法注解为多个，则 getAnnotation() 方法会返回 null
//
/*@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(RepeatableAnnotation.class)
@interface MethodAnnotation {

    String key();

    String value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface RepeatableAnnotation {
    MethodAnnotation[] value();
}

public class Method类 {
    
    @MethodAnnotation(key = "key1", value = "value1")
    @MethodAnnotation(key = "key2", value = "value2")
    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        // null
        System.out.println(method.getAnnotation(MethodAnnotation.class));
        MethodAnnotation[] annotationsByType = method.getAnnotationsByType(MethodAnnotation.class);
        // [@lang.reflect.MethodAnnotation(value=value1, key=key1), @lang.reflect.MethodAnnotation(value=value2, key=key2)]
        System.out.println(Arrays.toString(annotationsByType));
    }
}*/
//
//《getDeclaredAnnotationsByType(Class<T> annotationClass)》
//
//如果该方法对象存在指定类型的注解，则返回该注解数组，否则返回 null
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotationsByType() 方法与 getDeclaredAnnotationsByType() 方法作用相同
//
//《getAnnotations()》
//
//返回该方法对象上的所有注解，如果没有注解，则返回空数组
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotations() 方法与 getDeclaredAnnotations() 方法作用相同
//
/*@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MethodAnnotation {

    String key();

    String value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {

    String key();

    String value();
}

public class Method类 {
    
    @MethodAnnotation(key = "key1", value = "value1")
    @TestAnnotation(key = "key2", value = "value2")
    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations) {
            // @lang.reflect.MethodAnnotation(value=value1, key=key1)
            // @lang.reflect.Parameter.TestAnnotation(key=key2, value=value2)
            System.out.println(annotation);
        }
    }
}*/
//
//《getDeclaredAnnotations()》
//
//返回该方法对象上的所有注解，如果没有注解，则返回空数组
//
//只有类级别的注解会被继承得到，对于其他对象而言，getAnnotations() 方法与 getDeclaredAnnotations() 方法作用相同
//
//《getModifiers()》
//
//返回修饰该方法对象修饰符的整数形式，使用 Modifier 类对其进行解码
//
/*public class Method类 {
    
    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        // public
        System.out.println(Modifier.toString(method.getModifiers()));
    }
}*/

//《getName()》
//
//返回方法对象名称
//
/*public class Method类 {
    
    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        // test
        System.out.println(method.getName());
    }
}*/
//
//《isAnnotationPresent(Class<? extends Annotation> annotationClass)》
//
//如果该方法对象上有指定类型的注解，则返回 true，否则为 false
//
/*@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MethodAnnotation {

    String key();

    String value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {

    String key();

    String value();
}
public class Method类 {

    @MethodAnnotation(key = "key", value = "value")
    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        // true
        System.out.println(method.isAnnotationPresent(MethodAnnotation.class));
    }
}*/
//
//《isVarArgs()》
//
//如果该方法对象的参数中存在可变参，则返回 true，否则为 false
//可变参数即参数个数可变。
/*public class Method类 {

    public void test(String ... args) {}
    public void test1(String a) {}
    public void test2(int ...n) {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test", String[].class);
        // true
        System.out.println(method.isVarArgs());

        Method method1 = Method类.class.getDeclaredMethod("test1", String.class);
        // false
        System.out.println(method1.isVarArgs());
        
        Method method2 = Method类.class.getDeclaredMethod("test2", int[].class);
        // true
        System.out.println(method2.isVarArgs());
    }
}*/
//
//《getDeclaringClass()》
//
//返回该方法对象表示的方法所在类的 Class 对象
//
/*public class Method类 {

    public void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test");
        Class<?> declaringClass = method.getDeclaringClass();
        // class 反射.MethodTest
        System.out.println(declaringClass);
    }
}*/
//
//《getAnnotatedParameterTypes()》
//
//返回一个 AnnotatedType 对象数组，这些对象表示使用类型来指定由该可执行文件表示的方法或构造函数的形式参数类型
//
/*public class Method类 {

    public void test(String name, Integer age) {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test", String.class, Integer.class);
        AnnotatedType[] annotatedParameterTypes = method.getAnnotatedParameterTypes();
        for (AnnotatedType annotatedParameterType : annotatedParameterTypes) {
            // class java.lang.String
            // class java.lang.Integer
            System.out.println(annotatedParameterType.getType());
        }
    }
}*/
//
//《getParameterAnnotations()》
//
//返回一组注解数组，这些注解以声明顺序修饰该方法对象的参数
//
/*@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@interface ParameterAnnotation {

    String key();

    String value();
}
public class Method类 {

    public void test(@ParameterAnnotation(key = "key1", value = "value1") String name,
                     @ParameterAnnotation(key = "key2", value = "value2") Integer age,
                     @ParameterAnnotation(key = "key3", value = "value3") Integer[] solary) {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getDeclaredMethod("test", String.class, Integer.class,Integer[].class);
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        // [[@反射.ParameterAnnotation(key="key1", value="value1")], [@反射.ParameterAnnotation(key="key2", value="value2")]]
        System.out.println(Arrays.deepToString(parameterAnnotations));
        System.out.println(method.getParameterCount());//3

        //获取参数变量注解的具体值
        Parameter[] para=method.getParameters();
        for (Parameter p:para) {
        	if (p.isAnnotationPresent(ParameterAnnotation.class)) {
        		ParameterAnnotation paraValue=(ParameterAnnotation) p.getAnnotation(ParameterAnnotation.class);
        		System.out.println(paraValue.key()+"  "+paraValue.value());
        	}
        }
    }
}*/
//
//《getParameterCount()》
//
//返回该方法对象的参数个数 (无论是显式声明的还是隐式声明的或不声明的)
//
//public class MethodTest {
//
//    public void test(String name, Integer age) {}
//
//    public static void main(String[] args) throws Exception {
//        Method method = MethodTest.class.getDeclaredMethod("test", String.class, Integer.class);
//        // 2
//        System.out.println(method.getParameterCount());
//    }
//}
//
//《getParameters()》
//
//返回一个参数对象数组，该数组表示该方法对象的所有参数
//
//public class MethodTest {
//
//    public void test(String name, Integer age) {}
//
//    public static void main(String[] args) throws Exception {
//        Method method = MethodTest.class.getDeclaredMethod("test", String.class, Integer.class);
//        Parameter[] parameters = method.getParameters();
//        for (Parameter parameter : parameters) {
//            // java.lang.String name
//            // java.lang.Integer age
//            System.out.println(parameter);
//        }
//    }
//}
//
//《getDefaultValue()》
//
//返会该注解方法对象表示的成员默认值
//
//如果成员属于基本数据类型，则返回对应的包装类实例
//
//如果没有默认值或者该方法实例不表示注解方法，则返回 null
//
/*@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MethodAnnotation {

    String key() default "default key";

    String value() default "default value";
}

public class Method类 {

    public static void main(String[] args) throws Exception {
        Method key = MethodAnnotation.class.getMethod("key");
        Method value = MethodAnnotation.class.getMethod("value");
        Object defaultValue1 = key.getDefaultValue();
        Object defaultValue2 = value.getDefaultValue();
        // default key
        System.out.println(defaultValue1);
        // default value
        System.out.println(defaultValue2);

        Method[] keys = MethodAnnotation.class.getDeclaredMethods();
        for (Method m:keys) {
        	System.out.println(m.getDefaultValue());
        }
    }
}*/
//
//《getParameterTypes()》
//
//返回一个 Class 对象数组，该数组以声明顺序表示该方法对象的参数对象 (擦除泛型)
//
/*public class Method类<T> {

    public void test(T t, LinkedList<Integer> list) {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test", Object.class, LinkedList.class);
        Class<?>[] parameterTypes = method.getParameterTypes();
        // [class java.lang.Object, class java.util.LinkedList]
        System.out.println(Arrays.toString(parameterTypes));
    }
}*/
//
//《getReturnType()》
//
//返回一个 Class 对象，该 Class 对象表示该方法对象的返回对象 (擦除泛型)
//
/*public class Method类<T> {

    public T test(T t) {
        return t;
    }

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test", Object.class);
        Class<?> returnType = method.getReturnType();
        // class java.lang.Object
        System.out.println(returnType);
    }
}*/
//
//《getGenericReturnType()》
//
//返回一个 Type 对象，该 Type 对象表示该方法对象的返回类型 (保留泛型)
//
/*public class Method类<U> {

    public U test(U t) {
        return t;
    }

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test", Object.class);
        Type genericReturnType = method.getGenericReturnType();
        // T
        System.out.println(genericReturnType);//U
    }
}*/
//
//《getExceptionTypes()》
//
//返回一个 Class 对象数组，该数组表示由该方法对象抛出的异常对象 (擦除泛型)
//
/*public class Method类<T> {

    public <T extends Exception> void test() throws T, NullPointerException {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        Class<?>[] exceptionTypes = method.getExceptionTypes();
        // [class java.lang.Exception, class java.lang.NullPointerException]
        System.out.println(Arrays.toString(exceptionTypes));
    }
}*/
//
//《getGenericExceptionTypes()》
//
//返回一个 Type 对象数组，该数组表示由该方法对象抛出的异常类型 (保留泛型)
//
/*public class Method类<T> {

    public <T extends Exception> void test() throws T, NullPointerException {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        Type[] genericExceptionTypes = method.getGenericExceptionTypes();
        // [T, class java.lang.NullPointerException]
        System.out.println(Arrays.toString(genericExceptionTypes));
    }
}*/
//
//《getTypeParameters()》
//
//返回一个 TypeVariable 对象数组，该数组表示该方法对象声明列表上的类型变量数组
//
/*public class Method类<T, V> {

    public <T, V> void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        TypeVariable<Method>[] typeParameters = method.getTypeParameters();
        // [T, V]
        System.out.println(Arrays.toString(typeParameters));
    }
}*/
//
//《toString()》
//
//返回该方法对象的字符串表示形式 (擦除泛型)
//
/*public class Method类<T, V> {

    public <T, V> void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        // public void lang.reflect.Method类.test()
        System.out.println(method.toString());
    }
}*/
//
//《toGenericString()》
//
//返回该方法对象的字符串表示形式 (保留泛型)
//
/*public class Method类<T, V> {

    public <T, V> void test() {}

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        // public <T,V> void lang.reflect.MethodTest.test()
        System.out.println(method.toGenericString());
    }
}*/
//
//《isAccessible()》
//
//获取该方法对象的可访问标志
//
/*class MethodTest {

    private void test() {}
}

public class Method类 {

    public static void main(String[] args) throws Exception {
        Method method = MethodTest.class.getDeclaredMethod("test");
        // false
        System.out.println(method.isAccessible());
    }
}*/
//
//《setAccessible(boolean flag)》
//
//设置该方法对象的可访问标志
//
//在其他类里调用该方法对象时，如果该方法为私有方法，需要设置访问标志为 true，否则会报异常
//
/*class MethodTest {

    private void test() {}
}

public class Method类 {

    public static void main(String[] args) throws Exception {
        Method method = MethodTest.class.getDeclaredMethod("test");
        method.setAccessible(true);
        // test
        System.out.println(method.getName());
        //true
        System.out.println(method.isAccessible());
    
    }
}*/
//
//《isDefault()》
//
//判断该方法对象是否为默认方法，如果是则返回 true，否则为 false
//
/*interface Interface {

    default void test() {
        System.out.println("这是一个默认方法");
    }
}

public class Method类 implements Interface {

    public static void main(String[] args) throws Exception {
        Method method = Method类.class.getMethod("test");
        // true
        System.out.println(method.isDefault());
    }
}*/
//
//isSynthetic()
//
//判断该方法对象是否为合成方法，如果是则返回 true，否则为 false
//
//在内部类 InnerClass 中，name 是一个私有属性，而我们在外部类 MethodTest 中，直接引用了这个属性，因此编译器会生成一个合成方法，
//用于绕开 private 私有属性的限制
//
public class Method类 {

    private class InnerClass {
        private String name = "小明";
        private void a() {}
    }

    public static void main(final String[] arguments) {
        InnerClass innerClass = new Method类().new InnerClass();
        innerClass.name="aaaa";
        // name: 小明
        System.out.println("name: " + innerClass.name);
//        Method[] declaredMethods = innerClass.getClass().getDeclaredMethods();
        Method[] declaredMethods = InnerClass.class.getDeclaredMethods();
        System.out.println(declaredMethods.length);
        for (Method declaredMethod:declaredMethods) {
            // 【static java.lang.String lang.reflect.MethodTest$InnerClass.access$100(lang.reflect.MethodTest$InnerClass)】 
//        	isSynthetic(): true
            System.out.println("【" + declaredMethod + "】" + " isSynthetic(): " + declaredMethod.isSynthetic());
        }
    }
}



//
//有关 synthetic 的相关内容，小伙伴可以看下这里
//
//Java 中冷门的 synthetic 关键字原理解读
//isBridge()
//
//判断该方法对象是否桥接方法，如果是则返回 true，否则为 false
//
//桥接方法: 是 JDK1.5 引入泛型后，为了使 Java 的泛型方法生成的字节码和 1.5 版本前的字节码相兼容，由编译器自动生成的方法
//
//public interface Interface<T> {
//
//    T test(T t);
//}
//
//public class MethodTest implements Interface<String> {
//
//    @Override
//    public String test(String str) {
//        return str;
//    }
//
//    public static void main(final String[] arguments) {
//        Method[] declaredMethods = MethodTest.class.getDeclaredMethods();
//        for (Method declaredMethod : declaredMethods) {
//            //【public static void lang.reflect.MethodTest.main(java.lang.String[])】 isBridge(): false
//            //【public java.lang.String lang.reflect.MethodTest.test(java.lang.String)】 isBridge(): false
//            //【public java.lang.Object lang.reflect.MethodTest.test(java.lang.Object)】 isBridge(): true
//            System.out.println("【" + declaredMethod + "】" + " isBridge(): " + declaredMethod.isBridge());
//        }
//    }
//}
